Recursion:

Fibonacci sequence: 

Positions:	0	1	2	3	4 ...
Values: 	0	1	1	2	3 ...

fib function mapping positions to values:
fib(0) = 0 and fib(1) = 1

fib(n) = fib(n-1) + fib(n-2)

First approach: recursive

Time complexity: O(2^n)
Space complexity: O(n)

fib(3) --- fib(1)

|

fib(2) --- fib(1)

|

fib(0)

Fibonacci of 30: 2 million calls
Fibonacci of 31: 4 million
Fibonacci of 32: 7 million calls

Second approach: Dynamic programming <==> Recursion + caching (top-down approach) - Memoization

Cache where the size = n + 1 and it will be used to hold the computed values (intermediate results)

int[] n = {2};
foo(n);
System.out.println(n[0]); // 5


void foo(int[] n) {
	n[0] = 5;
}


Third approach: Bottom up dynamic programming
Time complexity: O(n)
Space complexity: O(1)

prevprev + prev = current

- LeetCode 50: power of x

First solution: time complexity O(N), space complexity O(1) (solution used a for loop)
Second solution (recursive): time complexity O(log2(N)), space complexity: O(log2(N))

3^7 = 3^(2^2 + 2 + 1) = 3^(2^2) * 3^2 * 3^1

3^5 = 3^(2^2 + 0 * 2 + 1) = 3^(2^2) * 3^(0 * 2) * 3^1






























